<?php

class Nuo
{

    /**
     * @var int
     */
    static protected $_siteId = 1;

    /**
     * @var request
     */
    static protected $_request = null;

    /**
     * @var Response
     */
    static protected $_response = null;

    /**
     * table prefix
     * @var string
     */
    static protected $_tablePrefix = 'nuo_';

    /**
     * object kinds
     * @var array
     */
    static protected $_kinds = array();

    /**
     * apis array
     * @var array
     */
    static protected $_apis = array();

    /**
     * cached table
     * @var array
     */
    static protected $_tables = array();

    /**
     * @var user
     */
    static protected $_viewer = null;

    /**
     * get current site id
     * @return int
     */
    static public function getSiteId()
    {
        return self::$_siteId;
    }

    /**
     * @param string $name
     * @return string
     */
    static public function getTableName($name)
    {
        return self::$_tablePrefix . $name;
    }

    /**
     * get current viewer
     * @return user
     */
    static public function getViewer()
    {
        if (null == self::$_viewer)
        {

        }
        return self::$_viewer;
    }

    /**
     * set current viewer
     * @param User $user
     * @return void
     */
    static public function setViewer($user)
    {
        self::$_viewer = $user;
    }

    /**
     * @param array $kinds
     * @return void
     */
    static public function setKinds($kinds)
    {
        self::$_kinds = $kinds;
    }

    /**
     * get all kind spect
     * @return string
     */
    static public function getKinds()
    {
        return self::$_kinds;
    }

    /**
     * get kind spec
     * @param string $name
     * @return string
     */
    static public function getKind($name)
    {
        return isset(self::$_kinds[$name]) ? self::$_kinds[$name] : null;
    }

    /**
     * set kind spec
     * @param string $name
     * @param string $spec
     * @return void
     */
    static public function setKind($name, $spec)
    {
        self::$_kinds[$name] = $spec;
    }

    /**
     * @param string $name
     */
    static public function getApi($name)
    {
        if (isset(self::$_apis[$name]))
        {
            return self::$_apis[$name];
        }
        $class = implode('_', array_map('nuo_inflect_string', explode('.', str_replace('@', '.api.', $name))));

        if (!self::loadClass($class))
        {
            throw new Nuo_Exception("api {$name}[$class] not found.");
        }

        return self::$_apis[$name] = new $class;
    }

    /**
     * @param string $name / kind / short name of table
     * @return Nuo_Db_Table
     */
    static public function getTable($name)
    {
        if (isset(self::$_tables[$name]))
        {
            return self::$_tables[$name];
        }

        /**
         * XXX: if we define more detail for each content type, besure to check
         * here.
         */
        if (isset(self::$_kinds[$name]))
        {
            $class = self::$_kinds[$name];
        }

        if (!$class)
        {
            $class = implode('_', array_map('nuo_inflect_string', explode('.', str_replace('@', '.model.table.', $name))));
        }

        if (!self::loadClass($class))
        {
            throw new Nuo_Exception("invalid table name {$name} [$class]");
        }
        return self::$_tables[$name] = new $class;
    }

    /**
     * get main request
     * @return Request
     */
    static public function getRequest()
    {
        if (null == self::$_request)
        {
            self::$_request = self::__initMainRequest();
        }
        return self::$_request;
    }

    /**
     * get main response object
     * @return Response
     */
    static public function getResponse()
    {
        if (null == self::$_response)
        {
            self::$_response = new Response;

        }
        return self::$_response;
    }

    /**
     * @param Request $request
     * @return void
     */
    static public function setRequest(Request $request)
    {
        self::$_request = $request;
    }

    /**
     * set main response object
     * @param Response $response
     * @return void
     */
    static public function setResponse(Response $response)
    {
        self::$_response = $response;
    }

    /**
     * get controller class
     * @return string
     */
    static public function getControllerClass($string)
    {
        return implode('_', array_map('nuo_inflect_string', explode('.', str_replace('@', '.controller.', $string))));

    }

    /**
     * get action method
     * @return string
     */
    static public function getActionMethod($string)
    {
        $string = nuo_inflect_string($string);
        return strtolower(substr($string, 0, 1)) . substr($string, 1) . 'Action';
    }

    static protected function __initMainRequest()
    {
        return new Request( array(
            'controllerName' => 'core@admin.index',
            'actionName' => 'index'
        ));
    }

    /**
     * execute request
     * @param Request $request
     * @param Response $response
     * @return $response
     */
    static public function executeRequest(Request $request, Response $response = null)
    {
        if (null == $response)
        {
            $response = self::getResponse();
        }

        $response -> setContent($request -> dispatch());

        self::executeResponse($request, $response);

        return $response;
    }

    /**
     * execute response
     * @param Request $request
     * @param Response $response
     * @return void
     */
    static public function executeResponse($request, $response)
    {
        // execute response.
        $format = $request -> getParam('format', null);

        if (null == $format)
        {
            echo View::renderLayout($request);
        }
        else
        {
            echo $response -> getContent();
        }
    }

    /**
     * check the class exists and load in explit cal
     * @param string $class $class name
     * @return bool  true if loaded and false if not found.
     */
    static public function loadClass($class)
    {
        return class_exists($class, false) or self::__autoload($class);
    }

    /**
     * @param string $class   class name to autoload call by
     * spl_autoload_register
     * @return bool true if found|false if othewise
     */
    static public function __autoload($class)
    {

        /**
         * find in module path.
         */
        $sub = str_replace('_', '/', strtolower($class)) . '.php';

        /**
         * find in module path
         */
        if (file_exists($file = NUO_MODULE_PATH . $sub))
        {
            require_once $file;
            if (class_exists($class))
            {
                return true;
            }
        }

        /**
         * find in library
         */

        if (file_exists($file = NUO_LIBRARY_PATH . str_replace('_', '/', $class) . '.php'))
        {
            require_once $file;
            if (class_exists($class))
            {
                return true;
            }
        }
        return false;
    }

}
